package org.jeecg.activiti.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.shiro.SecurityUtils;
import org.jeecg.activiti.entity.ActReModelFormData;
import org.jeecg.activiti.entity.ActReModelFormDeployment;
import org.jeecg.activiti.entity.ActivitiConstant;
import org.jeecg.activiti.entity.ProcessNodeVo;
import org.jeecg.activiti.service.IActHiModelFormDataService;
import org.jeecg.activiti.service.IActReModelExtendService;
import org.jeecg.activiti.service.IActReModelFormDataService;
import org.jeecg.activiti.service.IActReModelFormDeploymentService;
import org.jeecg.activiti.service.IActivitiInstanceService;
import org.jeecg.activiti.service.IActivitiTaskService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.online.cgform.entity.OnlCgformHead;
import org.jeecg.modules.online.cgform.service.IOnlCgformFieldService;
import org.jeecg.modules.online.cgform.service.IOnlCgformHeadService;
import org.jeecg.modules.online.cgform.util.SqlSymbolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 流程实例管理
 */
@RestController
@RequestMapping("/activiti/instance")
@Api(tags = "流程实例管理")
public class ActivitiInstanceController {

    @Autowired
    private IActReModelFormDataService iActReModelFormDataService;

    @Autowired
    private IActivitiInstanceService iActivitiInstanceService;

    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private IActHiModelFormDataService iActHiModelFormDataService;
    
    @Autowired
    private IOnlCgformHeadService onlCgformHeadService;
    
    @Autowired
    private IOnlCgformFieldService fieldService;
    
    @Autowired
    private IActReModelFormDeploymentService iActReModelFormDeploymentService;
    
    @Autowired
    private IActReModelExtendService actReModelExtendService;
    
    @Autowired
    private IActivitiTaskService iActivitiTaskService;
    
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /*通过流程定义id获取第一个任务节点*/
    @AutoLog(value = "流程-通过流程定义id获取第一个任务节点")
    @ApiOperation(value="流程-通过流程定义id获取第一个任务节点", notes="通过流程定义id获取第一个任务节点，包含可供选择的审批人、网关信息等")
    @RequestMapping(value = "/getFirstNode", method = RequestMethod.GET)
    public Result<ProcessNodeVo> getFirstNode(@ApiParam(value = "流程定义Id" ,required = true) String processDefinitionId){
        ProcessNodeVo node = iActivitiInstanceService.getFirstNode(processDefinitionId);
        return Result.OK(node);
    }

    /**
     * 启动流程示例
     */
    @GetMapping("/startInstance")
    @ApiOperation(value = "开始流程实例", notes = "开始流程实例")
    @Transactional
    public Result<Object> startInstance(@ApiParam(name="formDataId", value="表单数据Id", required = true) @RequestParam("formDataId") String formDataId,
    		HttpServletRequest request) {
        ActReModelFormData actReModelFormData = iActReModelFormDataService.getById(formDataId);
        if (actReModelFormData.getStatus() == 1) {
            return Result.error("该任务不能重复提交");
        }
        @SuppressWarnings("unchecked")
		Map<String, Object> variables = JSONObject.toJavaObject(JSONObject.parseObject(actReModelFormData.getFormData()), Map.class);

        // 获取当前登录用户
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // 设置流程发起人
        Authentication.setAuthenticatedUserId(sysUser.getUsername());

        // 启动流程实例
        ProcessInstance pi = runtimeService.startProcessInstanceById(actReModelFormData.getProcessDefinitionId(), formDataId, variables);
        // 将流程实例的ID，写入流程表单数据中
        iActReModelFormDataService.update(new UpdateWrapper<ActReModelFormData>()
                .set("status", ActivitiConstant.HANDLE_STATUS_HLZ)
                .set("process_instance_id", pi.getId())
                .eq("id", formDataId));
        // 将流程表单数据保存到历史表
        iActHiModelFormDataService.saveHiFormData(actReModelFormData, pi.getId());

        // 发送待办消息
        iActivitiInstanceService.handleBacklogMsg(pi, sysUser);

        // 发起流程抄送处理
        iActivitiInstanceService.handleProcessDuplicate(actReModelFormData, variables, pi.getId(), sysUser);

        return Result.OK();
    }
    
    /**
     * 启动流程示例
     */
    @GetMapping("/startOnlInstance")
    @ApiOperation(value = "开始流程实例", notes = "开始流程实例")
    @Transactional
    public Result<Object> startOnlInstance(@ApiParam(name="formDataId", value="表单数据Id", required = true) @RequestParam("formDataId") String formDataId,
    		@ApiParam(name="tableId", value="表单Id", required = true) @RequestParam("tableId") String tableId,
    		HttpServletRequest request) {
    	
    	OnlCgformHead head = onlCgformHeadService.getById(tableId);
    	if (head == null) {
            return Result.error("实体不存在");
        }
    	Map<String, Object> map;
		map = this.fieldService.queryBpmData(tableId, head.getTableName(), formDataId);
		map = SqlSymbolUtil.getValueType(map);
		
		if("1".equals(map.get("bpm_status"))){
			return Result.error("该任务不能重复提交");
		}
		
        // 获取当前登录用户
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 设置流程发起人
        Authentication.setAuthenticatedUserId(sysUser.getUsername());
        // 启动流程实例
        List<ActReModelFormDeployment> deps = iActReModelFormDeploymentService.list(new QueryWrapper<ActReModelFormDeployment>().eq("table_name", tableId).orderByDesc("create_time"));
        ProcessInstance pi = runtimeService.startProcessInstanceById(deps.get(0).getProcessDefinitionId(), formDataId, map);
    	
        map.put("bpm_status", ActivitiConstant.STATUS_DEALING+"");
    	this.fieldService.editFormBpmStatus(formDataId, head.getTableName(), ActivitiConstant.STATUS_DEALING+"");
    	
    	
    	ActReModelFormData actReModelFormData = new ActReModelFormData();
    	actReModelFormData.setCreateBy(sysUser.getUsername());
        actReModelFormData.setCreateTime(new Date());
        actReModelFormData.setModelId(deps.get(0).getModelId());
        actReModelFormData.setFormData(JSONObject.toJSONString(map));
        actReModelFormData.setProcessDefinitionId(deps.get(0).getProcessDefinitionId());
        actReModelFormData.setProcessInstanceId(pi.getId());
        actReModelFormData.setTableId(tableId);
        actReModelFormData.setTableName(head.getTableName());
        actReModelFormData.setType(1);
        actReModelFormData.setStatus(ActivitiConstant.STATUS_DEALING);
        actReModelFormData.setDataId(map.get("id")+"");
        iActReModelFormDataService.save(actReModelFormData);
        // 将流程表单数据保存到历史表
        iActHiModelFormDataService.saveHiFormData(actReModelFormData, pi.getId());

        // 发送待办消息
        iActivitiInstanceService.handleBacklogMsg(pi, sysUser);

        // 发起流程抄送处理
        // iActivitiInstanceService.handleProcessDuplicate(actReModelFormData, map, pi.getId(), sysUser);

        return Result.OK();
    }

    @GetMapping("/getFlowImgByInstanceId")
    @ApiOperation(value = "获取流程实例跟踪", notes = "获取流程实例跟踪")
    public Result<Object> getFlowImgByInstanceId(@ApiParam(value = "processInstanceId", name = "流程实例ID") String processInstanceId) {

        Result<Object> result = new Result<Object>();
        result.setResult(iActivitiInstanceService.getFlowImgByInstanceId(processInstanceId));
        result.setSuccess(true);

        return result;
    }
	    
    @GetMapping("/getDataByInstanceId")
    @ApiOperation(value = "获取流程实例跟踪", notes = "获取流程实例跟踪")
    public List<HistoricActivityInstance> getDataByInstanceId(@ApiParam(value = "processInstanceId", name = "流程实例ID") String processInstanceId) {

    	List<HistoricActivityInstance> list = processEngine.getHistoryService()
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .list();
        return list;
    }

    @GetMapping("/getFlowXmlByInstanceId")
    @ApiOperation(value = "获取流程实例跟踪XML", notes = "获取流程实例跟踪XML")
    public Result<Object> getFlowXmlByInstanceId(@ApiParam(value = "processInstanceId", name = "流程实例ID") String processInstanceId) {

        Result<Object> result = new Result<Object>();
        result.setResult(iActivitiInstanceService.getFlowXmlByInstanceId(processInstanceId));
        result.setSuccess(true);

        return result;
    }
}
